#include "vtor_buffer.h"
#include "vtor_string.h"

#ifdef __VTOR_BUFFER__

uint8_t VtorSingleBuffer_GetOverflowCnt(VtorSingleBuffer* buf)
{
	return buf->overflowCnt;
}

void VtorSingleBuffer_PushBuffer(VtorSingleBuffer* buf, uint8_t* inBuf, uint16_t inLen)
{
	// 获取当前还剩下多少空间
	while(inLen != 0)
	{
		uint16_t writeableLen = buf->maxLen - 1 - buf->pushIdx;
		// 写入的只能是两者中比较小的
		uint16_t curLen = inLen < writeableLen ? inLen : writeableLen;
		memcpy(buf->buf + buf->pushIdx, inBuf, curLen);
		while(curLen--)
		{
			buf->pushIdx++;
			if(buf->pushIdx == buf->popIdx)
			{
				buf->overflowCnt++; // 溢出
			}
		}
		// 写到边界，回到开头
		if(buf->pushIdx == buf->maxLen - 1)
		{
			buf->pushIdx = 0;
		}
		inLen -= curLen; // 减去上次剩余的，得到本次能写的
		inBuf += curLen; // 移动指针指向 下次要读取的数据
	}
	VtorSinglerBuffer_PushCallback(buf);
}

uint16_t VtorSingleBuffer_PopBuffer(VtorSingleBuffer* buf, uint8_t* outBuf, uint16_t expOutLen)
{
	uint16_t actualOutLen = 0;

	// 如果缓冲区是空的，直接返回0
	if (buf->pushIdx == buf->popIdx) {
		return 0;
	}

	while (actualOutLen < expOutLen)
	{
		// 计算从当前popIdx到缓冲区末尾或者pushIdx的前一个位置可以读取的长度
		uint16_t curLen = (buf->pushIdx < buf->popIdx) ?
			buf->pushIdx - buf->popIdx :
			buf->maxLen - buf->popIdx;

		memcpy(outBuf + actualOutLen, buf->buf + buf->popIdx, curLen);

		buf->popIdx += curLen;
		if (buf->popIdx == buf->maxLen)
		{
			buf->popIdx = 0; // 如果到达末尾，回到开头
		}
		actualOutLen += curLen;

		// 如果读取的长度已经达到期望的长度，或者没有更多的数据，退出循环
		if (actualOutLen >= expOutLen || buf->popIdx == buf->pushIdx)
		{
			break;
		}
	}
	VtorSinglerBuffer_PopCallback(buf);
	return actualOutLen;
}



uint8_t VtorMultiBuffer_GetOverflowCnt(VtorMultiBuffer* buf)
{
	return buf->overflowCnt;
}

void VtorMultiBuffer_SwitchInBuf(VtorMultiBuffer* buf)
{
	buf->inBuf[buf->inBufLen] = '\0'; // 放置一个字符串截断符
	uint8_t* nextInBuf = buf->inBuf + buf->maxBufLen;
	
	// 指向出界，调整指针
	if(nextInBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
	{
		nextInBuf = buf->bufArray;
	}
	// 保留最新数据，丢弃历史数据
	// 跳过正在读出的数据帧，保证此帧稳定
	if(nextInBuf == buf->outBuf)
	{
		nextInBuf = nextInBuf + buf->maxBufLen;
		buf->overflowCnt++; // 增加溢出次数  
		// 指向出界，调整指针
		if(nextInBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
		{
			nextInBuf = buf->bufArray;
		}
	}
	VtorMultiBuffer_SwitchInBufCallback(buf);
	buf->inBuf = nextInBuf;
	buf->inBufLen = 0; // 切换输入buf时，清空下标
}

void VtorMultiBuffer_SwitchOutBuf(VtorMultiBuffer* buf)
{
	buf->outBuf += buf->maxBufLen;
	// 指向出界，调整指针
	if(buf->outBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
	{
		buf->outBuf = buf->bufArray;
	}
	if(buf->outBuf == buf->inBuf)
	{
		VtorMultiBuffer_SwitchOutBufCallback(buf);
	}
}

void VtorMultiBuffer_AppendChar(VtorMultiBuffer* buf, uint8_t ch)
{
	// 针对指定buf的指定位置进行塞入
	buf->inBuf[buf->inBufLen++] = ch;
	if(VtorMultiBuffer_CheckSwitchInBuf(buf))
	{
		VtorMultiBuffer_SwitchInBuf(buf);
		VtorMultiBuffer_SwitchInBufCallback(buf);
	}
}


#endif // __VTOR_BUFFER__


